package com.qhx.rtkcloud.tcp;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;


import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

@Component
@Profile({"tcpserver"})
@ConfigurationProperties(prefix = "tcp.exchange")
@Configuration
public class TcpServerExChangePair extends TcpExchangePair {
    private static final Logger log = LoggerFactory.getLogger(TcpServerExChangePair.class);

//    private Pair<String, Integer> getIpAndPort(String ipAndPort) {
//       int  colon = ipAndPort.indexOf(":");
//       if (colon == -1 && ipAndPort.matches("-?\\d+(\\.\\d+)?")) { // 只有端口
//           return new Pair<>(null, Integer.parseInt(ipAndPort));
//       }
//
//       if (colon > 0) {
//          return new Pair<>(ipAndPort.substring(0, colon), Integer.parseInt(ipAndPort.substring(colon + 1)));
//       }
//       return null;
//    }


    private void processSocketClient(Socket client, TcpExchangeUnit tcpExchangeUnit) {

        try {
            client.setSoTimeout(1000 * 3);
            InputStream inputStream =  client.getInputStream();
            byte[] buffer = new byte[1024];
            int length =inputStream.read(buffer);
            if (length <= 0) {
                log.info("收到认证消息长度：" + length);
                client.close();
                return;
            }
            for (int i = 0; i < length; i++) {
                log.info("收到认证消息：i:" + i + ";" + buffer[i]);
                if (buffer[i] != i) {
                    log.info("错误 关闭");
                    client.close();
                    return;
                }
            }
            client.setSoTimeout(0);
        } catch (SocketException e) {
          log.error("", e);
        } catch (IOException e) {
            log.error("", e);
        }

        tcpExchangeUnit.setClient(client);
        Thread.setDefaultUncaughtExceptionHandler((t,e) -> {
            TcpExchangeUnit tcpExchangeUnit1 =  TcpExchangeUnit.TCP_EXCHANGE_UNIT_THREAD_LOCAL.get();
            if (tcpExchangeUnit1 != null && tcpExchangeUnit1.isConnectFreedom()
                    && !tcpExchangeUnit1.getPartner().isConnectFreedom()
                    &&tcpExchangeUnit1.getPartner().getClient() != null) {
                try {
                    tcpExchangeUnit1.getPartner().getClient().close();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }

            }
            TcpExchangeUnit.TCP_EXCHANGE_UNIT_THREAD_LOCAL.remove();
            e.printStackTrace();
        });

        tcpExchangeUnit.start();

    }

    private void connect(String host, Integer port, TcpExchangeUnit tcpExchangeUnit) {
            new Thread(() -> {
                try {
                    ServerSocket serverSocket =  new ServerSocket(port) ;
                    while (true) {
                       Socket client = serverSocket.accept();
                       log.info("accept client connection" + client.getInetAddress() + ":" + client.getPort() + ","
                               + client.getLocalAddress() + ":" + client.getLocalPort()); ;
                       if (!tcpExchangeUnit.isConnectFreedom() && tcpExchangeUnit.getPartner().isConnectFreedom()
                               && (tcpExchangeUnit.getPartner().getClient() == null || tcpExchangeUnit.getPartner().getClient().isClosed())) {
                           client.close();
                           continue;
                       }

                         new Thread(() -> processSocketClient(client, tcpExchangeUnit), "process-" + client.getInetAddress() + ":" + client.getPort() + "," + client.getLocalAddress() + ":" + client.getLocalPort()).start();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }, "startserver:" + port).start();
        }


    @Override
    protected void setSocket(String host, int port, TcpExchangeUnit tcpExchangeUnit) {
      connect(host, port, tcpExchangeUnit);
    }

}
